package com.hex.ds.hdrs.common.sort;


import com.hex.ds.hdrs.common.utils.HdrsDateUtil;
import com.hex.ds.hdrs.common.utils.ListUtil;
import com.hex.ds.hdrs.period.task.po.PeriodTask;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * 任务优先级排序队列
 */
@Slf4j
public class SortQueue {

    private LinkedList<PeriodTask> data = new LinkedList();

    private SortByStrategy sortByStrategy;

    private LinkedList<PeriodTask> delayTsData = new LinkedList();

    public LinkedList<PeriodTask> getList() {
        log.info("【SortQueue.getList】dataSize:{}===delayTsDataSize: {}", data.size(), delayTsData.size());
        LinkedList<PeriodTask> sortQueueList = new LinkedList<>();
        sortQueueList.addAll(data);
        sortQueueList.addAll(delayTsData);
        return sortQueueList;
    }

    public LinkedList<PeriodTask> getDelayTsData() {
        LinkedList<PeriodTask> sortQueueList = delayTsData;
        return sortQueueList;
    }

    public SortQueue(SortByStrategy sortByStrategy) {
        this.sortByStrategy = sortByStrategy;
    }

    /**
     * 向队列添加一个元素，只能加入到队尾
     *
     * @param srcTask
     */
    public void add(PeriodTask srcTask) {
        log.info("【SortQueue.add】srcTaskCode: {}", srcTask.getTaskCode());
        synchronized (data) {
            try {
                int i = 0;
                for (int j = 0; j < data.size(); j++) {
                    PeriodTask targetTask = data.get(j);
                    if (sortByStrategy.compare(srcTask, targetTask)) {
                        log.debug("【SortQueue.add】i:{},taskCode: {}", i, srcTask.getTaskCode());
                        data.add(i, srcTask);
                        return;
                    }
                    i++;
                }
                log.debug("【SortQueue.add】taskCode:{}", srcTask.getTaskCode());
                data.addLast(srcTask);
            } catch (Exception e) {
                log.error("【SortQueue.add】异常:{}", e.getMessage(), e);

                if (data.indexOf(srcTask) < 0) {
                    data.addLast(srcTask);
                }
            }
        }
    }

    /**
     * 添加置顶
     *
     * @param srcTask
     */
    public void addFirst(PeriodTask srcTask) {
        synchronized (data) {
            data.addFirst(srcTask);
        }
    }

    /**
     * 添加末尾
     *
     * @param srcTask
     */
    public void addLast(PeriodTask srcTask) {
        synchronized (data) {
            data.addLast(srcTask);
        }
    }

    /**
     * 移动任务到置顶
     *
     * @param srcTask
     */
    public void moveToFist(PeriodTask srcTask) {
        synchronized (data) {
            if (delayTsData.indexOf(srcTask) >= 0) {
                delayTsData.remove(srcTask);
                delayTsData.addFirst(srcTask);
            } else {
                data.remove(srcTask);
                data.addFirst(srcTask);
            }
        }
    }

    /**
     * 移动任务到末尾
     *
     * @param srcTask
     */
    public void moveToLast(PeriodTask srcTask) {
        synchronized (data) {
            if (delayTsData.indexOf(srcTask) >= 0) {
                delayTsData.remove(srcTask);
                delayTsData.addFirst(srcTask);
            } else {
                data.remove(srcTask);
                data.addFirst(srcTask);
            }
        }
    }

    /**
     * 升序
     *
     * @param srcTask
     */
    public void upSort(PeriodTask srcTask, int upIndex) {
        synchronized (data) {
            try {
                if (upIndex < data.size()) {
                    data.add(upIndex, srcTask);
                } else {
                    data.addFirst(srcTask);
                }
            } catch (Exception e) {
                log.error("【downSort】异常:{}", e.getMessage(), e);

                if (data.indexOf(srcTask) < 0) {
                    data.addLast(srcTask);
                }
            }
        }
    }

    /**
     * 降序
     *
     * @param srcTask
     */
    public void downSort(PeriodTask srcTask, int downIndex) {
        synchronized (data) {
            try {
                log.debug("【SortQueue.downSort】taskCode:{},bizDate:{}", srcTask.getTaskCode(), srcTask.getBizDate());
                if (downIndex < data.size()) {
                    data.add(downIndex, srcTask);
                } else {
                    data.addLast(srcTask);
                }
            } catch (Exception e) {
                log.error("【downSort】异常:{}", e.getMessage(), e);
                if (data.indexOf(srcTask) < 0) {
                    data.addLast(srcTask);
                }
            }
        }
    }


    /**
     * 添加到延迟list
     *
     * @param srcTask
     * @param delayTs
     */
    public void addToDelay(PeriodTask srcTask, int delayTs) {
        synchronized (delayTsData) {
            srcTask.setDelayTs(HdrsDateUtil.getMillis(new Date()) + delayTs);
            delayTsData.addLast(srcTask);
        }
    }


    /**
     * 查看队首元素，数据还保留在队列中
     *
     * @return
     */
    public PeriodTask peek() {
        synchronized (data) {
            if (data.isEmpty() && delayTsData.isEmpty()) {
                return null;
            }
            if (!delayTsData.isEmpty()) {
                PeriodTask task = delayTsData.getFirst();
                if (HdrsDateUtil.getMillis(new Date()) > task.getDelayTs()) {
                    return task;
                }
            }
            return data.getFirst();
        }
    }

    /**
     * 弹出元素，即获取队首元素并将其从队列中删除
     *
     * @return
     */
    public PeriodTask pop() {
        synchronized (data) {
            if (data.isEmpty() && delayTsData.isEmpty()) {
                return null;
            }
            if (!delayTsData.isEmpty()) {
                PeriodTask task = delayTsData.peekFirst();
                if (task != null && HdrsDateUtil.getMillis(new Date()) > task.getDelayTs()) {
                    return delayTsData.removeFirst();
                }
            }
            if (!data.isEmpty()) {
                return data.removeFirst();
            }
            return null;
        }
    }

    /**
     * 删除元素
     *
     * @return
     */
    public boolean remove(PeriodTask srcTask) {
        synchronized (data) {
            if (data.isEmpty() && delayTsData.isEmpty()) {
                return false;
            }
            log.info("【sortQueue remove】taskCode:{},bizDate:{}", srcTask.getTaskCode(), srcTask.getBizDate());
            if (delayTsData.contains(srcTask)) {
                delayTsData.remove(srcTask);
            } else if (data.contains(srcTask)) {
                data.remove(srcTask);
            } else {
                log.info("没删除【sortQueue remove】taskCode:{},bizDate:{}", srcTask.getTaskCode(), srcTask.getBizDate());
            }
            return true;
        }
    }

    /**
     * 删除元素
     *
     * @return
     */
    public boolean removeTask(PeriodTask srcTask) {
        synchronized (data) {
            if (data.isEmpty() && delayTsData.isEmpty()) {
                return false;
            }
            log.info("【sortQueue remove】taskCode:{},bizDate:{}", srcTask.getTaskCode(), srcTask.getBizDate());
            if (delayTsData.size() > 0) {
                Iterator<PeriodTask> delayTsDataIt = delayTsData.listIterator();
                while(delayTsDataIt.hasNext()){
                    PeriodTask periodTask = delayTsDataIt.next();
                    if (srcTask.getTaskCode().equals(periodTask.getTaskCode()) && srcTask.getBizDate().equals(periodTask.getBizDate())) {
                        delayTsDataIt.remove();
                    }
                }
            } else if (data.size() > 0) {
                Iterator<PeriodTask> dataIt = data.listIterator();
                while(dataIt.hasNext()){
                    PeriodTask periodTask = dataIt.next();
                    if (srcTask.getTaskCode().equals(periodTask.getTaskCode()) && srcTask.getBizDate().equals(periodTask.getBizDate())) {
                        dataIt.remove();
                    }
                }
            } else {
                log.info("没删除【sortQueue remove】taskCode:{},bizDate:{}", srcTask.getTaskCode(), srcTask.getBizDate());
            }
            return true;
        }
    }

    /**
     * 判断队列是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        synchronized (data) {
            return ListUtil.isEmpty(data) && ListUtil.isEmpty(delayTsData);
        }
    }

    /**
     * 清除队列中所有元素
     */
    public void clear() {
        synchronized (data) {
            data.clear();
            delayTsData.clear();
        }
    }

    /**
     * 判断队列是否为空
     *
     * @return
     */
    public boolean contain(PeriodTask task) {
        synchronized (data) {
            return data.contains(task) || delayTsData.contains(task);
        }
    }
}
